package cn.qmso.wxPay.v3;

import cn.qmso.wxPay.v3.base.Pay;
import cn.qmso.wxPay.v3.base.CombinedPayType;
import cn.qmso.wxPay.v3.base.WxPayV3Content;
import cn.qmso.wxPay.v3.config.WxPayV3Config;
import cn.qmso.wxPay.v3.paramEntity.combined.param.CombineCloseOrderParam;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.qmso.wxPay.v3.paramEntity.combined.param.CombinedPayParam;
import cn.qmso.wxPay.v3.paramEntity.combined.notify.CombinedNotifyVo;
import cn.qmso.wxPay.v3.paramEntity.combined.vo.selectorder.SelectComBinedOrderVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;


/**
 * @author lijuntao
 * 合单支付
 */
@Component
public class WxCombinedPay extends Pay {

    @Autowired
    private WxPayV3Config defaultWxPayV3Config;


    /**
     * 合单支付下单
     *
     * @param combinedPayType                请求类型
     * @param combinedPayParam      请求体 json字符串 此参数与微信官方文档一致
     * @return 请求结果
     */
    public String v3CombinedPayGet(CombinedPayType combinedPayType, CombinedPayParam combinedPayParam)
            throws NoSuchAlgorithmException, IOException, SignatureException, InvalidKeyException{
        return v3CombinedPayGet(combinedPayType,combinedPayParam,defaultWxPayV3Config);
    }

    public String v3CombinedPayGet(CombinedPayType combinedPayType, CombinedPayParam combinedPayParam, WxPayV3Config wxPayV3Config)
            throws NoSuchAlgorithmException, IOException, SignatureException, InvalidKeyException {
        Object body = postRequest(WxPayV3Content.URL_PRE + combinedPayType.getUrl(),
                null,
                JSONObject.toJSONString(combinedPayParam),
                wxPayV3Config);
        switch (combinedPayType.getUrl()) {
            case WxPayV3Content.COMBINE_APP_PAY_URL:
            case WxPayV3Content.COMBINE_JSAPI_PAY_URL:
                return JSONObject.parseObject(body.toString()).getString("prepay_id");
            case WxPayV3Content.COMBINE_NATIVE_PAY_URL:
                return JSONObject.parseObject(body.toString()).getString("code_url");
            case WxPayV3Content.COMBINE_H5_PAY_URL:
                return JSONObject.parseObject(body.toString()).getString("h5_url");
            default:
                return null;
        }
    }


    /**
     * 处理微信合单支付异步回调
     *
     * @param request 请求内容
     * @param response 响应内容
     * @return 支付的订单号
     */
    public CombinedNotifyVo notify(HttpServletRequest request, HttpServletResponse response) throws GeneralSecurityException, IOException {
        return notify(request,response,defaultWxPayV3Config);
    }

    public CombinedNotifyVo notify(HttpServletRequest request, HttpServletResponse response, WxPayV3Config wxPayV3Config) throws GeneralSecurityException, IOException {
        // 需要通过证书序列号查找对应的证书，verifyNotify 中有验证证书的序列号
        String plainText = verifyNotify(request, wxPayV3Config);
        //发送消息通知微信
        sendMessage(response, plainText);
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(plainText, new TypeReference<CombinedNotifyVo>() {});
    }

    /**
     * 查询合单支付订单信息
     * @param outTradeNo 订单号
     * @return 订单支付成功之后的详细信息
     */
    public SelectComBinedOrderVo selectOrder(String outTradeNo)
            throws URISyntaxException, NoSuchAlgorithmException, IOException, SignatureException, InvalidKeyException, IllegalAccessException {
        return selectOrder(outTradeNo,defaultWxPayV3Config);
    }

    /**
     * 查询合单支付订单信息
     * @param outTradeNo 订单编号
     * @param wxPayV3Config 微信v3配置
     * @return 订单支付成功之后的详细信息
     */
    public SelectComBinedOrderVo selectOrder(String outTradeNo, WxPayV3Config wxPayV3Config)
            throws URISyntaxException, NoSuchAlgorithmException, IOException, SignatureException, InvalidKeyException, IllegalAccessException {
        Object body = getRequest(String.format(WxPayV3Content.COMBINE_SELECT_ORDER_URL,outTradeNo),
                null,
                wxPayV3Config);
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(body.toString(),new TypeReference<SelectComBinedOrderVo>() {});
    }


    /**
     * 关闭未支付的合单支付的订单
     *
     * @param combineCloseOrderParam 订单信息
     * @return 订单关闭成功，无任何返回
     */
    public String closeCombinedOrder(CombineCloseOrderParam combineCloseOrderParam)
            throws NoSuchAlgorithmException, IOException, SignatureException, InvalidKeyException {
        return closeCombinedOrder(combineCloseOrderParam,defaultWxPayV3Config);
    }

    /**
     * 关闭未支付的合单支付的订单
     *
     * @param combineCloseOrderParam 订单信息
     * @param wxPayV3Config 配置信息
     * @return 订单关闭成功，无任何返回
     */
    public static String closeCombinedOrder(CombineCloseOrderParam combineCloseOrderParam, WxPayV3Config wxPayV3Config)
            throws NoSuchAlgorithmException, IOException, SignatureException, InvalidKeyException {
        Object body = postRequest(String.format(WxPayV3Content.COMBINE_CLOSE_ORDER_URL,combineCloseOrderParam.getCombine_out_trade_no()),
                null,
                JSONObject.toJSONString(combineCloseOrderParam),
                wxPayV3Config);
        return body.toString();
    }

}